import openpyxl
import pandas as pd
import plotly.graph_objects as go
import plotly.express as px
from plotly.subplots import make_subplots
import webbrowser
import tempfile
import os

# 设置文件路径
file_path = r"e:\Projects\program-py\LEARN-数据分析\CASE-dashboard_epidemic\香港各区疫情数据_20250322.xlsx"

def load_epidemic_data():
    """加载疫情数据"""
    try:
        # 检查文件是否存在
        if not os.path.exists(file_path):
            print(f"文件不存在: {file_path}")
            # 列出当前目录的Excel文件
            current_dir = os.path.dirname(file_path)
            print(f"当前目录: {current_dir}")
            print("目录中的文件:")
            for file in os.listdir(current_dir):
                if file.endswith(('.xlsx', '.xls')):
                    print(f"  - {file}")
            return None
            
        # 使用pandas读取Excel文件
        df = pd.read_excel(file_path)
        print("数据加载成功!")
        print(f"数据形状: {df.shape}")
        print(f"列名: {list(df.columns)}")
        print("\n前5行数据:")
        print(df.head())
        return df
    except Exception as e:
        print(f"加载数据时出错: {e}")
        return None

def analyze_epidemic_data(df):
    """分析疫情数据，计算每日新增和累计确诊"""
    print("\n数据预览:")
    print(df.head())
    print(f"\n数据类型:")
    print(df.dtypes)
    print(f"\n数据统计信息:")
    print(df.describe())
    
    # 查找可能的日期列和确诊列
    date_columns = [col for col in df.columns if any(keyword in str(col) for keyword in ['日期', 'date', '时间', 'time'])]
    confirm_columns = [col for col in df.columns if any(keyword in str(col) for keyword in ['确诊', 'confirm', '病例', 'case', '新增', '累计'])]
    
    print(f"\n可能的日期列: {date_columns}")
    print(f"可能的确诊列: {confirm_columns}")
    
    # 如果没有找到明确的列，使用前两列
    if not confirm_columns and len(df.columns) >= 2:
        confirm_columns = [df.columns[1]]
        print(f"使用第二列作为数据列: {confirm_columns[0]}")
    
    return df, date_columns, confirm_columns

def create_epidemic_dashboard(df):
    """创建疫情数据仪表板"""
    print(f"\n开始创建图表，数据列数: {len(df.columns)}")
    
    # 创建子图
    fig = make_subplots(
        rows=2, cols=2,
        subplot_titles=('每日新增确诊趋势', '累计确诊趋势', '各地区确诊分布', '风险等级分布'),
        specs=[[{"secondary_y": False}, {"secondary_y": False}],
               [{"secondary_y": False}, {"type": "pie"}]]
    )
    
    # 按日期汇总数据（显示全香港每日数据）
    daily_data = df.groupby('报告日期').agg({
        '新增确诊': 'sum',
        '累计确诊': 'max',
        '现存确诊': 'sum',
        '新增康复': 'sum',
        '新增死亡': 'sum'
    }).reset_index()
    
    print(f"按日期汇总后的数据: {daily_data.shape}")
    print(f"日期范围: {daily_data['报告日期'].min()} 到 {daily_data['报告日期'].max()}")
    
    # 按地区汇总最新数据
    latest_date = df['报告日期'].max()
    regional_data = df[df['报告日期'] == latest_date].copy()
    print(f"最新日期 {latest_date} 的地区数据: {regional_data.shape}")
    
    # 1. 每日新增确诊趋势（柱状图）
    fig.add_trace(
        go.Bar(x=daily_data['报告日期'], y=daily_data['新增确诊'], 
               name='每日新增确诊', marker_color='lightblue'),
        row=1, col=1
    )
    
    # 2. 累计确诊趋势（折线图）
    fig.add_trace(
        go.Scatter(x=daily_data['报告日期'], y=daily_data['累计确诊'], 
                   mode='lines+markers', name='累计确诊', 
                   line=dict(color='red', width=2)),
        row=1, col=2
    )
    
    # 3. 各地区确诊分布（柱状图）
    regional_data_sorted = regional_data.sort_values('累计确诊', ascending=False)
    fig.add_trace(
        go.Bar(x=regional_data_sorted['地区名称'], y=regional_data_sorted['累计确诊'], 
               name='各地区累计确诊', marker_color='orange'),
        row=2, col=1
    )
    
    # 4. 风险等级分布（饼图）
    risk_distribution = df['风险等级'].value_counts()
    fig.add_trace(
        go.Pie(labels=risk_distribution.index, values=risk_distribution.values, 
               name="风险等级分布"),
        row=2, col=2
    )
    
    # 更新布局
    fig.update_layout(
        title_text="香港疫情数据分析仪表板",
        showlegend=True,
        height=800,
        title_x=0.5
    )
    
    # 更新x轴标签
    fig.update_xaxes(title_text="日期/区域", row=1, col=1)
    fig.update_xaxes(title_text="日期/区域", row=1, col=2)
    fig.update_xaxes(title_text="日期/区域", row=2, col=1)
    
    # 更新y轴标签
    fig.update_yaxes(title_text="确诊人数", row=1, col=1)
    fig.update_yaxes(title_text="累计确诊", row=1, col=2)
    fig.update_yaxes(title_text="确诊人数", row=2, col=1)
    
    return fig

def create_interactive_dashboard(df):
    """创建交互式仪表板"""
    # 按日期汇总数据
    daily_data = df.groupby('报告日期').agg({
        '新增确诊': 'sum',
        '累计确诊': 'max',
        '现存确诊': 'sum',
        '新增康复': 'sum',
        '新增死亡': 'sum'
    }).reset_index()
    
    # 创建时间序列图表
    fig = go.Figure()
    
    # 添加每日新增确诊
    fig.add_trace(go.Scatter(
        x=daily_data['报告日期'],
        y=daily_data['新增确诊'],
        mode='lines+markers',
        name='每日新增确诊',
        line=dict(color='blue', width=2),
        hovertemplate='日期: %{x}<br>新增确诊: %{y}<extra></extra>'
    ))
    
    # 添加现存确诊
    fig.add_trace(go.Scatter(
        x=daily_data['报告日期'],
        y=daily_data['现存确诊'],
        mode='lines+markers',
        name='现存确诊',
        line=dict(color='orange', width=2),
        hovertemplate='日期: %{x}<br>现存确诊: %{y}<extra></extra>'
    ))
    
    # 添加累计确诊
    fig.add_trace(go.Scatter(
        x=daily_data['报告日期'],
        y=daily_data['累计确诊'],
        mode='lines+markers',
        name='累计确诊',
        line=dict(color='red', width=3),
        hovertemplate='日期: %{x}<br>累计确诊: %{y}<extra></extra>'
    ))
    
    # 更新布局
    fig.update_layout(
        title="香港疫情数据时间序列分析",
        xaxis_title="日期",
        yaxis_title="确诊人数",
        height=600,
        title_x=0.5,
        hovermode='x unified',
        legend=dict(
            orientation="h",
            yanchor="bottom",
            y=1.02,
            xanchor="right",
            x=1
        )
    )
    
    return fig

def save_and_open_html(fig, filename="epidemic_dashboard.html"):
    """保存图表为HTML文件并在浏览器中打开"""
    # 保存到临时文件
    temp_dir = tempfile.gettempdir()
    html_file = os.path.join(temp_dir, filename)
    
    # 保存HTML文件
    fig.write_html(html_file)
    
    print(f"\n图表已保存到: {html_file}")
    print("正在在浏览器中打开...")
    
    # 在浏览器中打开
    webbrowser.open(f'file://{html_file}')
    
    return html_file

def main():
    print("=" * 80)
    print("香港疫情数据可视化分析")
    print("=" * 80)
    
    # 加载数据
    df = load_epidemic_data()
    if df is None:
        print("无法加载数据，程序退出")
        return
    
    # 分析数据
    df, date_columns, confirm_columns = analyze_epidemic_data(df)
    
    # 创建仪表板
    print("\n正在创建可视化图表...")
    
    # 创建基础仪表板
    fig1 = create_epidemic_dashboard(df)
    
    # 创建交互式仪表板
    fig2 = create_interactive_dashboard(df)
    
    # 保存并打开图表
    if fig1 is not None:
        html_file1 = save_and_open_html(fig1, "epidemic_dashboard_basic.html")
        print(f"基础仪表板已保存到: {html_file1}")
    
    if fig2 is not None:
        html_file2 = save_and_open_html(fig2, "epidemic_dashboard_interactive.html")
        print(f"交互式仪表板已保存到: {html_file2}")
    
    # 输出数据摘要
    print("\n数据摘要:")
    print(f"  数据时间范围: {df['报告日期'].min()} 到 {df['报告日期'].max()}")
    print(f"  涵盖地区数: {df['地区名称'].nunique()}")
    print(f"  总新增确诊: {df['新增确诊'].sum():,}")
    print(f"  最大累计确诊: {df['累计确诊'].max():,}")
    print(f"  总死亡人数: {df['累计死亡'].max():,}")
    
    print("\n" + "=" * 80)
    print("分析完成! 图表已在浏览器中打开")
    print("=" * 80)

if __name__ == "__main__":
    main() 